
#ifndef IP_H_INCLUDED
#define IP_H_INCLUDED
typedef struct obj
{
    int height;
    int width;
    int **data;
} objdef;

int ***zeropadding(int ***img, int m,int n, int k)
{
    int ***new_img, row, col,depth;
    new_img=alloc3Dint(m+2,n+2,k);


      for(row=0;row<m;row++)
      {
	for(col=0;col<n;col++)
	{
	  for(depth=0;depth<k;depth++)
         {
	      new_img[row+1][col+1][depth]=img[row][col][depth];
	}
      }
    }
    return new_img;
}

int ***g_zeropadding(int ***img, int m,int n, int k, int w)
{
    int ***new_img, row, col,depth;
    new_img=alloc3Dint(m+w,n+w,k);


      for(row=0;row<m;row++)
      {
	for(col=0;col<n;col++)
	{
	  for(depth=0;depth<k;depth++)
         {

	   new_img[row+(int)floor((w/2))][col+(int)floor((w/2))][depth]=img[row][col][depth];
	}
      }
    }


    return new_img;
}

int **g_zeropadding2D(int **img, int m,int n,  int w)
{
    int **new_img, row, col;
    new_img=alloc2Dint(m+w,n+w);


   for(row=0;row<m;row++)
      {
            for(col=0;col<n;col++)
            {
                        new_img[row+(int)floor((w/2))][col+(int)floor((w/2))]=img[row][col];

            }
    }


    return new_img;
}

int **zeropadding2D(int **img, int m,int n)
{
    int **new_img, row, col;
    new_img=alloc2Dint(m+2,n+2);


      for(row=0;row<m;row++)
      {
	for(col=0;col<n;col++)
	{

	      new_img[row+1][col+1]=img[row][col];
	}
      }

    return new_img;
}

int ***dIx(int ***img,int m, int n, int k)
{
      int  row, col,depth;
    int ***Ix;
      Ix=alloc3Dint(m,n,k);

           for(row=1;row<m-1;row++)
	    {
	      for(col=1;col<n-1;col++)
	      {
		 for(depth=0;depth<k;depth++)
		  {

		   Ix[row][col][depth]=fabs((img[row+1][col-1][depth]+2*img[row+1][col][depth]+img[row+1][col+1][depth])
		    -(img[row-1][col-1][depth]+2*img[row-1][col][depth]+img[row-1][col+1][depth]));
	      }
	    }
	}
	return Ix;
}

int **dIx_pgm(int **img,int m, int n)
{
      int  row, col;
    int **Ix;
      Ix=alloc2Dint(m,n);

           for(row=1;row<m-1;row++)
	    {
	      for(col=1;col<n-1;col++)
	      {


		   Ix[row][col]=fabs((img[row+1][col-1]+2*img[row+1][col]+img[row+1][col+1])-(img[row-1][col-1]+2*img[row-1][col]+img[row-1][col+1]));

	    }
	}
	return Ix;
}
int ***dIy(int ***img,int m, int n, int k)
{
      int row, col,depth;
       int ***Iy;
      Iy=alloc3Dint(m,n,k);

           for(row=1;row<m-1;row++)
	    {
	      for(col=1;col<n-1;col++)
	      {
		for(depth=0;depth<k;depth++)
		{

		   Iy[row][col][depth]=fabs((img[row-1][col+1][depth]+2*img[row][col+1][depth]+img[row+1][col+1][depth])-(img[row-1][col-1][depth]+2*img[row][col-1][depth]+img[row+1][col-1][depth]));
	      }
	    }
	}
	return Iy;
}
int **dIy_pgm(int **img,int m, int n)
{
      int row, col;
       int **Iy;
      Iy=alloc2Dint(m,n);

           for(row=1;row<m-1;row++)
	    {
	      for(col=1;col<n-1;col++)
	      {


		   Iy[row][col]=fabs((img[row-1][col+1]+2*img[row][col+1]+img[row+1][col+1])-(img[row-1][col-1]+2*img[row][col-1]+img[row+1][col-1]));

	    }
	}
	return Iy;
}
int ***dIx2(int ***img, int m, int n, int k)
{
      int ***Ix2, row, col, depth;
      Ix2=alloc3Dint(m,n,k);
      for(row=0;row<m;row++)
      {
	  for(col=0;col<n;col++)
	  {

	      for(depth=0;depth<k;depth++)
	      {
		    Ix2[row][col][depth]=img[row][col][depth]*img[row][col][depth];
	      }

	  }
      }
  return Ix2;
}

int ***dIxy(int ***img1, int ***img2, int m, int n, int k)
{
      int ***Ixy, row, col, depth;
      Ixy=alloc3Dint(m,n,k);
      for(row=0;row<m;row++)
      {
	  for(col=0;col<n;col++)
	  {

	      for(depth=0;depth<k;depth++)
	      {
		    Ixy[row][col][depth]=img1[row][col][depth]*img2[row][col][depth];
	      }

	  }
      }
  return Ixy;
}
int **dIxy_pgm(int **img1, int **img2, int m, int n)
{
      int **Ixy, row, col;
      Ixy=alloc2Dint(m,n);
      for(row=0;row<m;row++)
      {
	     for(col=0;col<n;col++)
	     {

	        Ixy[row][col]=img1[row][col]*img2[row][col];
        }
      }
  return Ixy;
}
int ***moment_gen(int ***img1,int m, int n, int k, int patch)
{
    int ***img2,  row, col,depth,temp, wi, wj,new_row=0,new_col=0,w1,w2;
    w1=(int)floor(m/patch);
    w2=(int)floor(n/patch);
    img2=alloc3Dint(w1+1, w2+1, k);
    for(row=0;row+patch<m;row=row+patch)
    {
      for(col=0;col+patch<n;col=col+patch)
      {

	  for(depth=0;depth<k;depth++)
	  {
	       temp=0;
	        printf("%d\t%d\t%d\t%d\t%d\n",row,col,new_row,new_col,temp);
	       for(wi=row;wi<row+patch;wi++)
		{
		      for(wj=col;wj<col+patch;wj++)
		      {

				  temp=temp+img1[wi][wj][depth];
			}
		}

	img2[new_row][new_col][depth]=temp;
	 }
	new_col++;
	}
	new_col=0;
      new_row++;
    }
   return img2;
}





int ***convolve(int ***img1,int m, int n, int k )
{
  int ***img2, ***img3, row, col,depth,temp, wi, wj;

  img2=alloc3Dint(m, n, k);
  img3=zeropadding(img1,m,n,k);
    for(row=1;row<m+1;row++)
  {
    for(col=1;col<n+1;col++)
    {
      for(depth=0;depth<k;depth++)
      {
      temp=0;
        for(wi=-1;wi<2;wi++)
	{
	  for(wj=-1;wj<2;wj++)
	  {

	    temp=temp+img3[row+wi][col+wi][depth];
	  }
	}
	img2[row-1][col-1][depth]=temp;
      }
    }
  }
  return img2;
}


int ***dIt(int ***img_array1,int ***img_array2,int m,int n,int k)
{
  int ***It, row, col,depth;
      It=alloc3Dint(m,n,k);

           for(row=0;row<m;row++)
	    {
	      for(col=0;col<n;col++)
	      {
		for(depth=0;depth<k;depth++)
		{

		  It[row][col][depth]=img_array2[row][col][depth]-img_array1[row][col][depth];
	      }
	    }
	}
	return It;
}
/*int **Normalize(int **img1_array,int m, int n)
{
    int row, col;


           for(row=0;row<m;row++)
	    {
	      for(col=0;col<n;col++)
	      {


		  if(img1_array[row][col]<0)
		    {
		       img1_array[row][col]=0;
		    }
		    if(img1_array[row][col]>255)
		    {
			 img1_array[row][col]=255;
		    }
		}
	      }

	  return img1_array;
}*/
int **Normalize_grad(int **img1, int m, int n)
{
        int row, col, min, max;
        min=img1[0][0];
        max=img1[0][0];
        for(row=0; row<m; row++)
        {
            for(col=0; col<n; col++)
            {
                    if(min>img1[row][col])
                    {
                       min=img1[row][col];
                    }
                    if(max<img1[row][col])
                    {
                       max=img1[row][col];
                    }

            }
        }
        printf("%d\t%d\n", min, max);
       for(row=0; row<m; row++)
       {
            for(col=0;col<n; col++)
            {
                img1[row][col]=(int)(((float)(img1[row][col]-min)/(max-min))*(float)(255-90))+90;
            }
       }
    return img1;
}
float **normalize(float **img1, int m, int n, int L)
{
  int row, col;
  float  min, max;
  min=img1[0][0];
  max=img1[0][0];

        for(row=0; row<m; row++)
        {
            for(col=0; col<n; col++)
            {
                    if(min>img1[row][col])
                    {
                       min=img1[row][col];
                    }
                    if(max<img1[row][col])
                    {
                       max=img1[row][col];
                    }

            }
        }
       
       for(row=0; row<m; row++)
       {
            for(col=0;col<n; col++)
            {
                img1[row][col]=((float)(img1[row][col]-min)/(max-min))*L;
            }
       }
    return img1;
}

int ***Normalize_grad_ppm(int ***img1, int m, int n, int depth)
{
        int row, col,k, min, max;
        for(k=0;k<depth;k++)
        {
        min=img1[0][0][k];
        max=img1[0][0][k];
        for(row=0; row<m; row++)
        {
            for(col=0; col<n; col++)
            {
                    if(min>img1[row][col][k])
                    {
                       min=img1[row][col][k];
                    }
                    if(max<img1[row][col][k])
                    {
                       max=img1[row][col][k];
                    }

            }
        }

       for(row=0; row<m; row++)
       {
            for(col=0;col<n; col++)
            {
                img1[row][col][k]=(int)(((float)(img1[row][col][k]-min)/(max-min))*(float)(255));
            }
       }
    }

    img_write_ppm(img1,"normalized_image.ppm");
    return img1;
}
/*float min(float x, float y)
{
  if(x<=y)
    return x;
  else
    return y;
}

int *newton_raphson(int ***gxx, int ***gyy, int ***gxy, int ***gx, int ***gy, int ***img1, int ***img2, int x, int y, int patch_size)
{
    int temp, sum1,  *new_coord, row, col, org_x, org_y, i, j,iter;
    float **jx, **jx_inv,sum2, fx[2],error,d_change[2],det;
    org_x=x;
    org_y=y;
    sum1=0;
    jx=alloc2Dfloat(2,2);


    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(row+x)*(row+x)*gxx[row+x][col+y][0];
	  }
    }
  jx[0][0]=(float)sum1;
  sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(row+x)*(row+x)*gxy[row+x][col+y][0];
	  }
    }
  jx[0][1]=(float)sum1;
  jx[1][0]=(float)sum1;
  sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(row+x)*(col+y)*gxx[row+x][col+y][0];
	  }
    }
  jx[0][1]=(float)sum1;
  jx[1][0]=(float)sum1;
 sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(row+x)*(col+y)*gxy[row+x][col+y][0];
	  }
    }
  jx[0][3]=(float)sum1;
  jx[1][2]=(float)sum1;
  jx[2][1]=(float)sum1;
  jx[3][0]=(float)sum1;
  sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(row+x)*gxx[row+x][col+y][0];
	  }
    }
  jx[0][4]=(float)sum1;
  jx[4][0]=(float)sum1;
  sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(row+x)*gxy[row+x][col+y][0];
	  }
    }
  jx[0][5]=(float)sum1;
  jx[1][4]=(float)sum1;
  jx[4][1]=(float)sum1;
  jx[5][0]=(float)sum1;
   sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(row+x)*(row+x)*gyy[row+x][col+y][0];
	  }
    }
  jx[1][1]=(float)sum1;
  sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(row+x)*(col+y)*gyy[row+x][col+y][0];
	  }
    }
  jx[1][3]=(float)sum1;
  jx[3][1]=(float)sum1;
  sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(row+x)*gyy[row+x][col+y][0];
	  }
    }
  jx[1][5]=(float)sum1;
  jx[5][1]=(float)sum1;
  sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(col+y)*(col+y)*gxx[row+x][col+y][0];
	  }
    }
  jx[2][2]=(float)sum1;

  sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(col+y)*(col+y)*gxy[row+x][col+y][0];
	  }
    }
  jx[2][3]=(float)sum1;
  jx[3][2]=(float)sum1;

sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(col+y)*gxx[row+x][col+y][0];
	  }
    }
  jx[2][4]=(float)sum1;
  jx[4][2]=(float)sum1;
sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(col+y)*gxy[row+x][col+y][0];
	  }
    }
  jx[2][5]=(float)sum1;
  jx[5][2]=(float)sum1;
  jx[3][4]=(float)sum1;
  jx[4][3]=(float)sum1;
sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(col+y)*gyy[row+x][col+y][0];
	  }
    }
  jx[3][5]=(float)sum1;
  jx[5][3]=(float)sum1;
sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(col+y)*(col+y)*gyy[row+x][col+y][0];
	  }
    }
  jx[3][3]=(float)sum1;
sum1=0;*/
   /* for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+gxx[row+x][col+y][0];
	  }
    }
  jx[0][0]=(float)sum1;

sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+gyy[row+x][col+y][0];
	  }
    }
  jx[1][1]=(float)sum1;
  sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+gxy[row+x][col+y][0];
	  }
    }
  jx[0][1]=(float)sum1;
  jx[1][0]=(float)sum1;
  det=jx[0][0]*jx[1][1]-jx[0][1]*jx[1][0];
  if(det>0)
  {
  jx_inv=inv(jx,2);
    new_coord=alloc1Dint(2);
  new_coord[0]=x;
  new_coord[1]=y;


  iter=0;
    do{
      sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(row+x)*(img2[new_coord[0]+row][new_coord[1]+col][0]-img1[row+x][col+y][0])*gx[row+x][col+y][0];
	  }
    }
fx[0]=(float)sum1;
sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(row+x)*(img2[new_coord[0]+row][new_coord[1]+col][0]-img1[row+x][col+y][0])*gy[row+x][col+y][0];
	  }
    }
fx[1]=(float)sum1;

sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(col+y)*(img2[new_coord[0]+row][new_coord[1]+col][0]-img1[row+x][col+y][0])*gx[row+x][col+y][0];
	  }
    }
fx[2]=(float)sum1;
sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(col+y)*(img2[new_coord[0]+row][new_coord[1]+col][0]-img1[row+x][col+y][0])*gy[row+x][col+y][0];
	  }
    }
fx[3]=(float)sum1;*/
/*sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(img2[new_coord[0]+row][new_coord[1]+col][0]-img1[row+x][col+y][0])*gx[row+x][col+y][0];
	  }
    }
fx[0]=(float)sum1;
sum1=0;
    for (row=0;row<patch_size;row++)
    {
	 for (col=0;col<patch_size;col++)
	  {
	      sum1=sum1+(img2[new_coord[0]+row][new_coord[1]+col][0]-img1[row+x][col+y][0])*gy[row+x][col+y][0];
	  }
    }
fx[1]=(float)sum1;
printf("\n%d\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n",iter,fx[0],fx[1],fx[2],fx[3],fx[4],fx[5]);
for(row=0;row<6;row++)
{
  for(col=0;col<6;col++)
  {
    printf("%f\t", jx_inv[row][col]);
  }
 printf("\n");
} */
/*for (row=0;row<2;row++)
{
  sum2=0;
  for(col=0;col<2;col++)
  {
      sum2=sum2+jx_inv[row][col]*fx[col];
  }
 d_change[row]=d_change[row]+sum2;
}
//printf("\n%d\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n",iter,d_change[0],d_change[1],d_change[2],d_change[3],d_change[4],d_change[5]);

 // d_change[0]=d_change[0]+1;
  //d_change[3]=d_change[3]+1;
 printf("\n%d\t%.2f\t%.2f\n",iter,d_change[0],d_change[1]);
new_coord[0]=new_coord[0]+d_change[0];
new_coord[1]=new_coord[1]+d_change[1];
sum2=0;
//printf("%d\t%d\t%d\n",iter,x,y,new_coord[0],new_coord[1]);
if(new_coord[0]<0||new_coord[0]+patch_size>240 ||new_coord[1]<0|| new_coord[1]+patch_size>320)
{
    new_coord[0]=(org_x-1);
    new_coord[1]=(org_y-1);
}
printf("%d\t%d\t%d\t%d\t%d\n", iter,org_x,org_y,new_coord[0],new_coord[1]);

for(row=0;row<patch_size;row++)
{
  for(col=0;col<patch_size;col++)
  {
     sum2=sum2+((img1[row+org_x][col+org_y][0]-img2[new_coord[0]+row][new_coord[1]+col][0])*(img1[row+org_x][col+org_y][0]-img2[new_coord[0]+row][new_coord[1]+col][0]));
  }
}
sum2=(float)sum2/(patch_size*patch_size);

error=sqrt(sum2);
iter++;
x=new_coord[0];
y=new_coord[1];
}while(fabs(error)>10&& iter<150);
  }
if(iter>=150)
{
  new_coord[0]=12345;
  new_coord[1]=12345;
}
return new_coord;
}*/

#else
#endif
